#include "Scene.h"
#include <osgViewer/ViewerEventHandlers>
#include "OGUIEventHandler.h"
#include "OKeySwitchManipulator.h"
#include "RoadMgr.h"
#include "ModelMgr.h"
#include "StatusMgr.h"
#include "core/CUtil.h"
#include "core/CElapsedTimer.h"

osg::ref_ptr<osgViewer::Viewer> Scene::s_viewer;
OGroup* Scene::s_root = nullptr;

#define NumMultiSamples 4

class RealizeOperationCallback : public osg::Operation {
public:
	void operator()(osg::Object* object) override {
		CUtil::checkGLMultisamplingStatus();
		OUtil::checkMultiSamplesStatus();
	}
};

struct MyDrawCallback : public osg::Camera::DrawCallback {
	void operator()(osg::RenderInfo& renderInfo) const override {
	}
};

void Scene::init() {
	osg::DisplaySettings::instance()->setNumMultiSamples(NumMultiSamples);

	s_viewer = new osgViewer::Viewer;
	s_viewer->setUpViewInWindow(0, 100, W3D, H3D);

	s_viewer->getDatabasePager()->setDoPreCompile(false);// forbid Pre-Compile because of high-dynamic-scene-updates

	s_viewer->setRealizeOperation(new RealizeOperationCallback);

	auto camera = new OCamera(s_viewer->getCamera());
	s_viewer->setCamera(camera);

	//camera->setPreDrawCallback(new MyDrawCallback);

	s_root = new OGroup;
	s_viewer->setSceneData(s_root);

	Cache::startAsyncLoadingZhiche();
	
	/****** debug ******/
	s_viewer->setCameraManipulator(new OKeySwitchManipulator(camera));
	s_viewer->addEventHandler(new osgViewer::StatsHandler);// Key=[S] x1(show) x2 x3 x4 x5(disappear) ......
		
	debugKeyEvents();
}

void Scene::run() {
	s_viewer->realize();// initialize rendering window and OpenGL context, loading OpenGL function pointers, etc.
	CElapsedTimer timer;
	while (isActive()) {
		RoadMgr::get()->updateEntities();
		ModelMgr::get()->updateEntities();
		StatusMgr::get()->updateEntities();
		s_viewer->frame();

		//static int i = 0;
		//std::cout << timer.elapsed() << "  ";
		//if (++i % 20 == 0) std::cout << std::endl;
		//timer.reset();
	}
}

void Scene::clear() {
	RoadMgr::get()->clear();
	ModelMgr::get()->clear();
	StatusMgr::get()->clear();
}

void Scene::debugKeyEvents() {
	return;
	static float scale = 1;
	static float x = 0;
	static float y = 0;
	static float z = 0;
	static float rotY = 0;

	auto entity = new Entity;
	CVector<P> vertices2d;
	float Y2d = 0.5;
	vertices2d << P(-1, 0) << P(1, 0) << P(0, -1);
	entity->setVertices(vertices2d, Y2d);
	entity->setColor("green");
	entity->install(Config::Shader_AnyFree);
	add(entity);

	s_viewer->addEventHandler(new OGUIEventHandler([=](osgGA::GUIEventAdapter::KeySymbol key) {
		switch (key) {
		case KEY(KP_Add):
			entity->setScale(scale += 0.1);
			LogI << "scale: " << scale << std::endl;
			break;
		case KEY(KP_Subtract):
			entity->setScale(scale -= 0.1);
			LogI << "scale: " << scale << std::endl;
			break;
			/**************************************************/
		case KEY(Home):
			entity->setRotation(rotY += 0.1);
			LogI << "rotY: " << rotY << std::endl;
			break;
		case KEY(End):
			entity->setRotation(rotY -= 0.1);
			LogI << "rotY: " << rotY << std::endl;
			break;
		case KEY(Up):
			entity->setPosition(glm::vec3(x, y, z -= 0.1));
			LogI << "position: (" << x << "," << y << "," << z << ")" << std::endl;
			break;
		case KEY(Down):
			entity->setPosition(glm::vec3(x, y, z += 0.1));
			LogI << "position: (" << x << "," << y << "," << z << ")" << std::endl;
			break;
		case KEY(Left):
			entity->setPosition(glm::vec3(x -= 0.1, y, z));
			LogI << "position: (" << x << "," << y << "," << z << ")" << std::endl;
			break;
		case KEY(Right):
			entity->setPosition(glm::vec3(x += 0.1, y, z));
			LogI << "position: (" << x << "," << y << "," << z << ")" << std::endl;
			break;
		default:
			break;
		}
	}));
}